#include "Snake.h"
#include "Frame.h"
#include "Strategy.h"


CSnake::CSnake(CFrame *pFrame)
    :m_pFrame(pFrame)
{
}


CSnake::~CSnake()
{
}


EMapUnitType CSnake::MoveSnake(EDirType eDir)
{
    Pos stHeadPos = GetSnakeHead();
    Pos stNewPos = stHeadPos;

    switch (eDir)
    {
    case EM_DIR_TYPE_UP:
        --stNewPos.iY;
        break;
    case EM_DIR_TYPE_DOWN:
        ++stNewPos.iY;
        break;
    case EM_DIR_TYPE_LEFT:
        --stNewPos.iX;
        break;
    case EM_DIR_TYPE_RIGHT:
        ++stNewPos.iX;
        break;
    default:
        return EM_MAP_UNIT_TYPE_MAX;
    }

    const EMapUnitType eMapUnitType = m_pFrame->GetMapUnitData(stNewPos.iX, stNewPos.iY).eType;
    const int iSnakeLength = GetSnakeLength();
    const Pos &stTail = GetSnakeTail();

    switch (eMapUnitType)
    {
    case EM_MAP_UNIT_TYPE_WALL:
    case EM_MAP_UNIT_TYPE_SNACKE:
        return eMapUnitType;
    case EM_MAP_UNIT_TYPE_NULL:
    {
        //擦掉蛇的尾巴
        m_pFrame->SetPosition(stTail.iX, stTail.iY);
        m_pFrame->Print(UIChar[EM_MAP_UNIT_TYPE_NULL]);
        MapUnitData &stMutableMapUnitData = m_pFrame->MutableMapUnitData(stTail.iX, stTail.iY);
        stMutableMapUnitData.eType = EM_MAP_UNIT_TYPE_NULL;
        break;
    }
    case EM_MAP_UNIT_TYPE_FOOD:
    {
        //吃到食物
        IncreaseSnakeLength();
        break;
    }
    default:
        return EM_MAP_UNIT_TYPE_MAX;
    }

    Pos *pSnake = MutableSnake();

    if (pSnake == NULL)
    {
        return EM_MAP_UNIT_TYPE_MAX;
    }

    const int iNewSnakeLength = GetSnakeLength();
    for (int iLength = iNewSnakeLength - 1; iLength > 0; --iLength)
    {
        pSnake[iLength] = pSnake[iLength - 1];
    }

    pSnake[0] = stNewPos;

    MapUnitData &stMutableMapUnitData = m_pFrame->MutableMapUnitData(stNewPos.iX, stNewPos.iY);
    stMutableMapUnitData.eType = EM_MAP_UNIT_TYPE_SNACKE;

    m_pFrame->SetPosition(stNewPos.iX, stNewPos.iY);
    m_pFrame->Print(UIChar[EM_MAP_UNIT_TYPE_SNACKE]);

    return eMapUnitType;
}


EDirType CSnake::MoveSnake()
{
    if (m_pStrategy == NULL)
    {
        return EM_DIR_TYPE_ERROR;
    }

    return m_pStrategy->GetDir();
}

bool CSnake::Init(vector<Pos> &vecPos)
{
    int iPosSize = (int)vecPos.size();
    if (iPosSize <= 0)
    {
        return false;
    }

    for (int iPosTmp = 0; iPosTmp < iPosSize - 1; ++iPosTmp)
    {
        if (!m_pFrame->IsNear(vecPos[iPosTmp], vecPos[iPosTmp + 1]))
        {
            return false;
        }
    }


    for (int iPosTmp = 0; iPosTmp < iPosSize; ++iPosTmp)
    {
        m_stSnake.stBody[iPosTmp] = vecPos[iPosTmp];
    }

    m_stSnake.iLength = iPosSize;

    return true;
}

void CSnake::SetStrategy(CStrategy *pStrategy)
{
    if (pStrategy == NULL)
    {
        return;
    }

    m_pStrategy = pStrategy;
}
